package com.kyg.tjtoolmanager.net.netty.hander;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.kyg.tjtoolmanager.App;
import com.kyg.tjtoolmanager.db.SQLiteUtils;
import com.kyg.tjtoolmanager.module.PersonInfo;
import com.kyg.tjtoolmanager.net.netty.bean.AccessBackDTO;
import com.kyg.tjtoolmanager.net.netty.bean.HeartBackDTO;
import com.kyg.tjtoolmanager.net.netty.bean.HeartRequestDTO;
import com.kyg.tjtoolmanager.net.netty.constant.LapiUriConstat;
import com.kyg.tjtoolmanager.net.netty.factory.ChannelFactory;
import com.kyg.tjtoolmanager.net.netty.factory.HttpResponseFactory;
import com.kyg.tjtoolmanager.net.netty.manager.DeviceChannelContext;
import com.kyg.tjtoolmanager.net.netty.manager.RequestSubscriptionThread;
import com.kyg.tjtoolmanager.net.netty.manager.ResponseDeviceManager;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;

import java.util.Date;
import java.util.Objects;


/**
 * Copyright (C),  2018-2025, ZheJiang Uniview Technologies Co., Ltd. All rights reserved.
 * <http://www.uniview.com/>
 * <p>
 * FileName : HttpHeartHandler
 *
 * @Author : s04180
 * Date     : 2019/12/30 17:04
 * DESCRIPTION:
 * <p>
 * History:
 * DATE        NAME        DESC
 */
public class LapiServerHandler extends SimpleChannelInboundHandler {

    /**
     * 设备序列号
     */
    public volatile String serialNo;

    /**
     * 读取通道,过滤并处理心跳消息
     *
     * @param ctx 通道上下文
     * @param msg 消息
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        try {
            //区分是response 还是 request
            if (msg instanceof FullHttpRequest) {
                FullHttpRequest httpRequest = (FullHttpRequest) msg;
                //请求uri
                String requestUri = httpRequest.uri();
                //消息体内容
                String content = httpRequest.content().toString(CharsetUtil.UTF_8);
                //心跳保活消息
                if (requestUri.contains(LapiUriConstat.HEART_URI)) {
                    //回包并存下设备的连接通道ctx
                    saveDeviceCtx(content, ctx);
                    heartResponse(ctx);
                } else if (httpRequest.uri().contains(LapiUriConstat.ACCESS_RECEIVE_URI)) {
                    // 设备上报的出入记录信息
//                    SQLiteUtils.insertLog(ctx.channel().remoteAddress() + "识别记录：" + content);

                    JSONObject jsonObject = JSON.parseObject(content);
                    Long seq = jsonObject.getLong("Seq"); //通知记录序号
                    Long uploadTime = jsonObject.getLong("Timestamp") * 1000;
                    int notificationType = jsonObject.getInteger("NotificationType");
                    long passTime = jsonObject.getJSONArray("FaceInfoList").getJSONObject(0).getLong("Timestamp") * 1000;
                    String faceData = jsonObject.getJSONArray("FaceInfoList").getJSONObject(0).getJSONObject("FaceImage").getString("Data");
                    //接收成功
                    accessResponse(ctx, seq, 0);
                    JSONArray array = jsonObject.getJSONArray("LibMatInfoList");
                    if (array.size() > 0) {
                        JSONObject person = (JSONObject) array.get(0);
                        PersonInfo personInfo = JSON.parseObject(person.getJSONObject("MatchPersonInfo").toJSONString(), PersonInfo.class);
                        SQLiteUtils.insertLog("personInfo：" + personInfo.toString());
                    }

                    if (ChannelFactory.isWorkerFaceIP(ctx.channel().remoteAddress().toString())) {
                        SQLiteUtils.insertLog("工作台=" + App.StartFaceLogin);
                        if (App.StartFaceLogin) {
                            //人脸识别
                            LapiServerFactory.dispatchFaceLogin(jsonObject.toJSONString());
                        }
                    } else {
                        //门禁识别
                        SQLiteUtils.insertLog("门禁 " + ctx.channel().remoteAddress().toString());
                    }
                } else {
//                    SQLiteUtils.insertLog("requestUri：" + requestUri);
                    SQLiteUtils.insertLog("其他上报：" + content);
                    // 其他请求信息暂未处理,直接透传到后面可自定义的 handle
                    ctx.fireChannelRead(msg);
                }
                // 平台请求,设备的回复消息
            } else if (msg instanceof FullHttpResponse) {
                FullHttpResponse response = (FullHttpResponse) msg;
                HttpResponseFactory.responseHandle(ctx, response);
            } else {
                ctx.fireChannelRead(msg);
            }
        } catch (
                Exception e) {
            SQLiteUtils.insertLog("Read [{}] channel msg[{}] failed for:{}" + ctx.channel().remoteAddress().toString()
                    + "  " + JSON.toJSONString(msg) + " " + e.getMessage());
        }

    }

    private void checkPerson() {

    }

    /**
     * 心跳回包拼装
     *
     * @return
     * @throws Exception
     */
    private void heartResponse(ChannelHandlerContext ctx) {
        HeartBackDTO heartBackDO = new HeartBackDTO(LapiUriConstat.HEART_URI, 0, new Date());
        ResponseDeviceManager.responseDevice(ctx, heartBackDO);
        SQLiteUtils.insertLog("[SERIAL_NO][{}] 心跳回包正常！客户端: " + serialNo + " IP：" + ctx.channel().remoteAddress());
    }

    /**
     * 响应终端
     * StatusCode：0：平台接收成功，1：平台接收失败
     * StatusString：Succeed/Common Fail
     * RecordID：通行记录ID（对应过人记录里的"Seq"字段）
     *
     * @param ctx
     * @param seq        记录id
     * @param statusCode 0-成功 1-失败
     */
    public void accessResponse(ChannelHandlerContext ctx, Long seq, Integer statusCode) {
        AccessBackDTO accessRecordBack = new AccessBackDTO(LapiUriConstat.ACCESS_RESPONSE_URI, statusCode, seq);
        ResponseDeviceManager.responseDevice(ctx, accessRecordBack);
    }


    /**
     * 保存链接
     *
     * @param strRequest
     * @param ctx
     * @throws Exception
     */
    private void saveDeviceCtx(String strRequest, ChannelHandlerContext ctx) {
        HeartRequestDTO request = JSONObject.parseObject(strRequest, HeartRequestDTO.class);
        String serialNo = request.getStrDeviceCode();
        this.serialNo = serialNo;
        DeviceChannelContext deviceCtx = ChannelFactory.getChannelBySerialNo(serialNo);
        if (Objects.isNull(deviceCtx)) {
            //添加设备的链接通道
            ChannelFactory.addChannel(serialNo, ctx);

            //订阅告警
            RequestSubscriptionThread requestSubscriptionThread = new RequestSubscriptionThread();
            requestSubscriptionThread.setSerialNo(serialNo);
            requestSubscriptionThread.start();
        } else {
            // 刷新设备对应的链接通道
            ChannelFactory.freshChannel(serialNo, ctx);
        }
    }

    /**
     * 添加channel时
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) {
        Channel incoming = ctx.channel();
        SQLiteUtils.insertLog("SimpleChatClient:" + incoming.remoteAddress() + "通道被添加");
    }

    /**
     * 删除channel时
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) {
        Channel channel = ctx.channel();
        SQLiteUtils.insertLog("SimpleChatClient:{},通道被删除" + channel.remoteAddress());
    }

    /**
     * 服务端监听到客户端不活动
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        //服务端接收到客户端掉线通知
        Channel incoming = ctx.channel();
        SQLiteUtils.insertLog("SimpleChatClient: {}  掉线" + incoming.remoteAddress());
    }

    /**
     * 服务端监听到客户端活动
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        //服务端接收到客户端上线通知
        Channel incoming = ctx.channel();

        SQLiteUtils.insertLog("SimpleChatClient:" + incoming.remoteAddress() + "上线");


    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        Channel channel = ctx.channel();
        SQLiteUtils.insertLog("SimpleChatClient:{},异常断开,{}" + channel.remoteAddress() + cause);
        //出现异常判断下通道是否还可用
        if (!channel.isWritable()) {
            ctx.close();
            HttpResponseFactory.removeResponse(ctx);
        }
    }
}
